#include once"wgeSystem.bi"
#include once"wgeSprite.bi"

#include once"world.bi"
#include once"player.bi"
#include once"enemy.bi"
#include once"spell.bi"
#include once"potion.bi"


 

dim game as __wgeSystem ptr=new __wgeSystem(640,480,32,0)
game->setState("start")

dim start as __wgeSprite ptr=new __wgeSprite("start.bmp")
dim win as __wgeSprite ptr=new __wgeSprite("win.bmp")
dim lose as __wgeSprite ptr=new __wgeSprite("lose.bmp")

dim player as __player ptr=new __player("character.bmp","spell.bmp","aimer.bmp",1000,500,300)
dim ground as __world ptr=new __world(game,"tile.bmp")
  
'make enemies, only activate several though
dim allEnemy(1 to 50) as __enemy ptr
dim temp as __wgeSprite ptr=new __wgeSprite("enemy.bmp")
dim i as integer
for i=lbound(allEnemy) to ubound(allEnemy)
    allEnemy(i)=new __enemy(game,temp,2,200)
    allEnemy(i)->setColliding(1)
    if i<=1 then allEnemy(i)->activate(320,240,game->rand(-200,200),game->rand(-200,200),3.25)
next i

'make 3 potions, 1 health,1 mana,1 both
dim potions(1 to 6) as __potion ptr
for i=1 to 6 step 3
    potions(i)=new __potion("potions.bmp",1,0)
    potions(i+1)=new __potion("potions.bmp",0,1)
    potions(i+2)=new __potion("potions.bmp",1,1)
next i


while not key(KEY_ESC)
    game->beginStep
    
    
    select case game->getState()
        
        case "start"
        start->renderEx(game->buffer,320,240,0,1+.1*(sin(5*timer())))
        if keypressed() then game->setState("main")
        
        case "main"
        ground->render(game)
        
        'update and render the potions
        dim i as integer
        for i=lbound(potions) to ubound(potions)
            potions(i)->update(game,ground,player)
            potions(i)->render(game)
        next i


        dim a as integer
        
        dim enemycount as integer
        
        for i=lbound(allEnemy) to ubound(allEnemy)
            'if allEnemy(i)->getSize()<=.25 then allEnemy(i)->deactivate()
            
            allEnemy(i)->update(game,ground)
            allEnemy(i)->render(game)
            
            
            if allEnemy(i)->getActive()=0 then continue for
            
            enemycount+=1
            
            if game->circleCollision(allEnemy(i)->getX(),allEnemy(i)->getY(),allEnemy(i)->getSize()*32/2,player->getX(),player->getY(),16) then
                if allEnemy(i)->getColliding()=0 then
                    allEnemy(i)->setColliding(1)
                    
                    'subtract health from player..
                    player->changeHealth(-50*allEnemy(i)->getSize())
                    
                endif
            else
                allEnemy(i)->setColliding(0)
            endif
            
            'detect collisions w/ player spells
            dim j as integer
            for j=lbound(player->spell) to ubound(player->spell)
                
                if player->spell(j)->getActive=0 then continue for
                
                if game->circleCollision(allEnemy(i)->getX(),allEnemy(i)->getY(),allEnemy(i)->getSize()*32/2,player->spell(j)->getX(),player->spell(j)->getY(),16) then
                    
                    allEnemy(i)->deactivate()
                    player->spell(j)->deactivate()
                    player->addKill()
                    
                    'add 2 smaller ones where this one died (if this ones size>.25
                    if allEnemy(i)->getSize()>.75 then
                        dim k as integer
                        for k=1 to 2
                            
                            dim l as integer
                            for l=lbound(allEnemy) to ubound(allEnemy)
                                if l<>i and allEnemy(l)->getActive()=0 then
                                    
                                    allEnemy(l)->activate(allEnemy(i)->getX(),allEnemy(i)->getY(),game->rand(-200,200),game->rand(-200,200),allEnemy(i)->getSize()-.5)
                                    exit for
                                    
                                endif
                            next l
                            
                        next k
                    endif
                    
                    
                    exit for
                    
                endif
                
            next j
            
            
        next i
        
        
        player->update(game,ground)
        player->render(game)
        
        if enemycount=0 then game->setState("win")
        enemycount=0
        
        case "lose"
        
        lose->renderEx(game->buffer,320,240,0,1+.1*(sin(5*timer())))
        
        case "win"
        
        win->renderEx(game->buffer,320,240,0,1+.1*(sin(5*timer())))
        
    end select
        
    
    game->endStep
wend


delete game


#include once"world.bi"
#include once"allegro.bi"

type __enemy
    
    private:
        active as ubyte

        sprite as __wgeSprite ptr
        
        x as single
        y as single
        xSpeed as single
        ySpeed as single
        
        rotation as single
        rotationSpeed as single
        
        size as single
        
        maxSpeed as single
        
        colliding as ubyte
        
    public:
        declare constructor(byval game as __wgeSystem ptr,byval as __wgeSprite ptr,byval as single,byval as single)
        declare destructor()
        
        declare sub update(byval as __wgeSystem ptr,byval as __world ptr)
        declare sub render(byval as __wgeSystem ptr)
        
        'x,y,xspeed,yspeed,size
        declare sub activate(byval as single,byval as single,byval as single,byval as single,byval as single)
        declare sub deactivate()
        
        declare function getActive() as ubyte
        
        declare function getX() as single
        declare function getY() as single
        declare function getSize() as single
        
        declare function getColliding() as ubyte
        declare sub setColliding(byval as ubyte)
        

end type

constructor __enemy(byval game as __wgeSystem ptr,byval sprite as __wgeSprite ptr,byval size as single,byval maxSpeed as single)

    this.sprite=sprite

    'size: 1=normal, so try 4 or 3.  When it is destroyed, makes 2 smallers ones with size of size-1
    this.size=size
    this.maxSpeed=maxSpeed
    
    this.rotation=game->randInt(0,359)
    this.rotationSpeed=game->rand(-100,100)

end constructor

sub __enemy.update(byval game as __wgeSystem ptr,byval world as __world ptr)
   
    if this.active=0 then return
    
    this.rotation+=this.rotationSpeed*game->getDelta()
    
    this.x+=this.xSpeed*game->getDelta()
    this.y+=this.ySpeed*game->getDelta()
    
    if this.y<=0 or this.y>=game->buffer->h then this.y=game->buffer->h-game->clampValue(this.y,0,game->buffer->h)
    if this.x<=0 or this.x>=game->buffer->w then this.x=game->buffer->w-game->clampValue(this.x,0,game->buffer->w)
    
    
    'detect collisions w/ walls and react
    if world->checkMap(int((this.x+(this.size*32/2)*game->polarity(this.xSpeed)+this.xSpeed*game->getDelta())/32)+1,int((this.y/32)+1))=1 then
        'this.xSpeed=0
        this.xSpeed*=-1
    endif
    if world->checkMap(int((this.x/32)+1),int((this.y+(this.size*32/2)*game->polarity(this.ySpeed)+this.ySpeed*game->getDelta())/32)+1)=1 then
        'this.ySpeed=0
        this.ySpeed*=-1
    endif
    
    'slowly grow bigger
    this.size=min(this.size+.015*game->getDelta(),3.25)
    
end sub

sub __enemy.render(byval game as __wgeSystem ptr)
    
    if this.active=0 then return
    
    this.sprite->renderEx(game->buffer,this.x,this.y,this.rotation,this.size)
    
end sub

sub __enemy.deactivate()
    
    this.active=0
    
end sub

sub __enemy.activate(byval x as single,byval y as single,byval xSpeed as single,byval ySpeed as single,byval size as single)
        
    this.active=1
    
    this.x=x
    this.y=y
    
    this.xSpeed=xSpeed
    this.ySpeed=ySpeed
    
    this.size=size

end sub

function __enemy.getX() as single
    return this.x
end function

function __enemy.getY() as single
    return this.y
end function

function __enemy.getSize() as single
    return this.size
end function

function __enemy.getActive() as ubyte
    return this.active
end function

function __enemy.getColliding() as ubyte
    return this.colliding
end function

sub __enemy.setColliding(byval colliding as ubyte)
    this.colliding=colliding
end sub

#include once"spell.bi"
#include once"world.bi"
#include once"allegro.bi"

type __player
    
    private:
    
        sprite as __wgeSprite ptr
        aimer as __wgeSprite ptr
               
        x as single
        y as single
        xSpeed as single
        ySpeed as single
        maxSpeed as single
        
        kills as integer
        
        health as single
        maxHealth as single
        
        mana as single
        maxMana as single
        
        canCast as ubyte
    
    public:
        spell(1 to 50) as __spell ptr
    
        declare constructor(byval as string,byval as string,byval as string,byval as integer,byval as integer,byval as single)
        declare destructor()
        
        declare sub render(byval as __wgeSystem ptr)
        declare sub update(byval as __wgeSystem ptr,byval as __world ptr)
        
        declare sub addKill()
        
        declare function getX() as single
        declare function getY() as single
        
        declare sub changeHealth(byval as single)
        declare sub changeMana(byval as single)
    
end type

constructor __player(byval character as string,byval spell as string,byval aimer as string,byval maxHealth as integer,byval maxMana as integer,byval maxSpeed as single)

    this.sprite=new __wgeSprite(character)
    this.aimer=new __wgeSprite(aimer)
    
    dim temp as __wgeSprite ptr=new __wgeSprite(spell)
    dim i as integer
    for i=lbound(this.spell) to ubound(this.spell)
        this.spell(i)=new __spell(temp,maxSpeed+100)
    next i
        
    
    this.x=320
    this.y=240
    
    this.maxHealth=maxHealth
    this.health=this.maxHealth
    
    this.maxMana=maxMana
    this.mana=maxMana
    
    this.maxSpeed=maxSpeed
    this.xSpeed=0
    this.ySpeed=0
    
    this.canCast=1

end constructor

sub __player.render(byval game as __wgeSystem ptr)
          
    line(game->buffer,this.x,this.y,mouse_x,mouse_y,makecol(155,155,155))
    this.sprite->render(game->buffer,this.x,this.y)
    this.aimer->render(game->buffer,mouse_x,mouse_y)
    
    textout(game->buffer,font,"Stats",5,5,makecol(255,255,255))
    textout(game->buffer,font,"Kills:"+str$(this.kills),5,2*5+game->getTextHeight(),makecol(155,155,155))
    textout(game->buffer,font,"Health:"+str$(int(this.health))+"/"+str$(int(this.maxHealth)),5,3*5+2*game->getTextHeight(),makecol(255,0,0))
    textout(game->buffer,font,"Mana:"+str$(int(this.mana))+"/"+str$(int(this.maxMana)),5,4*5+3*game->getTextHeight(),makecol(0,0,255))    

end sub

sub __player.update(byval game as __wgeSystem ptr,byval world as __world ptr)
    
    if key(KEY_W) then
    
        this.ySpeed=max(this.ySpeed-400*game->getDelta(),-this.maxSpeed)
    
    elseif key(KEY_S) then
    
        this.ySpeed=min(this.ySpeed+400*game->getDelta(),this.maxSpeed)
    
    else
    
        this.ySpeed=this.ySpeed-(game->polarity(this.ySpeed)*(this.maxSpeed*.9)*game->getDelta())
    
    endif
    
    if key(KEY_A) then
    
        this.xSpeed=max(this.xSpeed-400*game->getDelta(),-this.maxSpeed)
    
    elseif key(KEY_D) then
    
        this.xSpeed=min(this.xSpeed+400*game->getDelta(),this.maxSpeed)
    
    else
    
        this.xSpeed=this.xSpeed-(game->polarity(this.xSpeed)*(this.maxSpeed*.9)*game->getDelta())
    
    endif
    
    'detect collisions w/ walls and react
'original:world->checkMap(int((this.x+16*game->polarity(this.xSpeed)+this.xSpeed*game->getDelta())/32)+1,int((this.y/32)+1))=1
    if world->checkMap(int((this.x+16*game->polarity(this.xSpeed)+this.xSpeed*game->getDelta())/32)+1,int(((this.y-16)/32)+1))=1 or world->checkMap(int((this.x+16*game->polarity(this.xSpeed)+this.xSpeed*game->getDelta())/32)+1,int(((this.y+16)/32)+1))=1 then
        this.xSpeed=0
    endif
'original:world->checkMap(int((this.x/32)+1),int((this.y+16*game->polarity(this.ySpeed)+this.ySpeed*game->getDelta())/32)+1)=1
    if world->checkMap(int(((this.x-16)/32)+1),int((this.y+16*game->polarity(this.ySpeed)+this.ySpeed*game->getDelta())/32)+1)=1 or world->checkMap(int(((this.x+16)/32)+1),int((this.y+16*game->polarity(this.ySpeed)+this.ySpeed*game->getDelta())/32)+1)=1 then
        this.ySpeed=0
    endif
    
    this.y+=this.ySpeed*game->getDelta()
    this.x+=this.xSpeed*game->getDelta()
    
    if this.y<=0 or this.y>=game->buffer->h then this.y=game->buffer->h-game->clampValue(this.y,0,game->buffer->h)
    if this.x<=0 or this.x>=game->buffer->w then this.x=game->buffer->w-game->clampValue(this.x,0,game->buffer->w)
    
    if mouse_b and 1 then
        if this.canCast=1 then
            
            if this.mana-10>0 then
                
                dim i as integer
                for i=0 to int(this.kills/200)
                    
                    
                    dim freeSpell as integer
                    for freeSpell=lbound(this.spell) to ubound(this.spell)
                        if this.spell(freeSpell)->getActive()=0 then exit for
                    next freeSpell
                    
                    if freeSpell<>ubound(this.spell) then
                        this.spell(freeSpell)->activate(game,this.x,this.y,mouse_x,mouse_y)
                    endif    
                    
                next i
                
                this.mana-=10
                
                
            endif
            
            this.canCast=0
        
        endif
    else
        
        this.canCast=1
        'slowly refill mana
        this.mana=min(this.mana+30*game->getDelta(),this.maxMana)

    endif
    
    'slowly add health
    this.health=min(this.health+5*game->getDelta(),this.maxHealth)

    'update spells
    dim i as integer
    for i=lbound(this.spell) to ubound(this.spell)
        this.spell(i)->update(game,world)
        this.spell(i)->render(game)
    next i
    
    'detect collisions w/ water and limit speed to waterSpeed
    if world->checkMap(int(this.x/32)+1,int(this.y/32)+1)=2 then
       this.xSpeed=max(min(this.xSpeed,this.maxSpeed/3),-this.maxSpeed/3)
       this.ySpeed=max(min(this.ySpeed,this.maxSpeed/3),-this.maxSpeed/3)
    endif
    'detect collision w/ lava and subtract health
    if world->checkMap(int(this.x/32)+1,int(this.y/32)+1)=3 then
        this.health=this.health-50*game->getDelta()
    endif
    
    if this.health<=0 then
        
        'gaveover
        game->setState("lose")
        
    endif

end sub


sub __player.addKill()
    this.kills+=1
end sub


function __player.getX() as single
    return this.x
end function

function __player.getY() as single
    return this.y
end function

sub __player.changeHealth(byval amount as single)
    this.health=max(min(this.health+amount,this.maxHealth),0.0)
end sub

sub __player.changeMana(byval amount as single)
    this.mana=max(min(this.mana+amount,this.maxMana),0.0)
end sub
#include once"world.bi"
#include once"allegro.bi"

type __potion
    
    private:
        texture as bitmap ptr
    
        x as single
        y as single
        
        
        health as ubyte
        mana as ubyte
        
    public:
        declare constructor (byval as string,byval as ubyte,byval as ubyte)
        declare destructor()
        
        declare sub update(byval as __wgeSystem ptr,byval as __world ptr,byval as __player ptr)
        declare sub render(byval as __wgeSystem ptr)
    
end type

constructor __potion(byval path as string,byval health as ubyte,byval mana as ubyte)

    this.texture=load_bitmap(path,0)
    this.health=health
    this.mana=mana

end constructor

destructor __potion()

    destroy_bitmap(this.texture)

end destructor

sub __potion.render(byval game as __wgeSystem ptr)
    
    if this.health=1 and this.mana=1 then
        masked_blit(this.texture,game->buffer,64,0,this.x,this.y,32,32)
    elseif this.health=1 then
        masked_blit(this.texture,game->buffer,0,0,this.x,this.y,32,32)
    elseif this.mana=1 then
        masked_blit(this.texture,game->buffer,32,0,this.x,this.y,32,32)
    endif
    
end sub

sub __potion.update(byval game as __wgeSystem ptr,byval world as __world ptr,byval player as __player ptr)
    
    if game->circleCollision(this.x,this.y,16,player->getX(),player->getY(),16)=1 then
        player->changeHealth(this.health*500)
        player->changeMana(this.mana*500)
        
        dim newx as single=0
        dim newy as single=0
        while world->checkMap(int(newx/32)+1,int(newy/32)+1)<>0
            newx=game->rand(0,640)
            newy=game->rand(0,480)
        wend
        
        this.x=int(newx/32)*32
        this.y=int(newy/32)*32     
        
    endif
    
    if this.x=0 or this.y=0 then
        dim newx as single=0
        dim newy as single=0
        while world->checkMap(int(newx/32)+1,int(newy/32)+1)<>0
            newx=game->rand(0,640)
            newy=game->rand(0,480)
        wend
        
        this.x=int(newx/32)*32
        this.y=int(newy/32)*32
    endif
    
end sub







'bug:
'shoot the middle of the left side.  the spell bounces.



#include once"world.bi"
#include once"allegro.bi"

type __spell
    
    private:
    
        active as ubyte
        
        sprite as __wgeSprite ptr
        x as single
        y as single
        rotation as single
        speed as single
        
        bounce as integer
    
    public:
        declare constructor(byval as __wgeSprite ptr,byval as single)
        declare destructor()
        
        declare function getActive() as ubyte
        declare sub activate(byval as __wgeSystem ptr,byval as single,byval as single,byval as single,byval as single)
        declare sub deactivate()
        declare sub update(byval as __wgeSystem ptr,byval as __world ptr)
        declare sub render(byval as __wgeSystem ptr)
        
        declare function getX() as single
        declare function getY() as single
     
end type

constructor __spell(byval sprite as __wgeSprite ptr,byval speed as single)

    this.sprite=sprite
    this.speed=speed

end constructor

function __spell.getActive() as ubyte
    return this.active
end function

sub __spell.activate(byval game as __wgeSystem ptr,byval startX as single,byval startY as single,byval targetX as single,byval targetY as single)
    
    this.active=1
    this.x=startX
    this.y=startY
    this.rotation=game->getAngle(startX,startY,targetX,targetY)+game->rand(-10,10)
    
end sub

sub __spell.deactivate()
    
    this.active=0
    this.bounce=0
    
end sub

sub __spell.render(byval game as __wgeSystem ptr)

    if this.active=0 then return

    this.sprite->render(game->buffer,this.x,this.y,this.rotation)
    
end sub

sub __spell.update(byval game as __wgeSystem ptr,byval world as __world ptr)
    
    if this.active=0 then return
    
    this.x=game->newX(this.x,this.rotation,this.speed*game->getDelta())
    this.y=game->newY(this.y,this.rotation,this.speed*game->getDelta())

    if this.x<0 or this.x>game->buffer->w or this.y<0 or this.y>game->buffer->h then
        this.deactivate
    endif
    
    if world->checkMap(int((this.x+16)/32)+1,int((this.y/32)+1))=1 then
        this.rotation=game->wrapValue(this.rotation+180,0,359)
        this.rotation=270+(270-this.rotation)
        this.x-=4
        this.bounce+=1
    endif
    if world->checkMap(int((this.x-16)/32)+1,int((this.y/32)+1))=1 then
        this.rotation=game->wrapValue(this.rotation+180,0,359)
        this.rotation=90+(90-this.rotation)
        this.x+=4
        this.bounce+=1
    endif
    if world->checkMap(int(this.x/32)+1,int(((this.y+16)/32)+1))=1 then
        this.rotation=game->wrapValue(this.rotation+180,0,359)
        this.rotation=180+(180-this.rotation)
        this.y-=4
        this.bounce+=1
    endif
    if world->checkMap(int(this.x/32)+1,int(((this.y-16)/32)+1))=1 then
        this.rotation=game->wrapValue(this.rotation+180,0,359)
        this.rotation=0+(0-this.rotation)
        this.y+=4
        this.bounce+=1
    endif
    
    if this.bounce>=10 then
        this.deactivate
        this.bounce=0
    endif

end sub

function __spell.getX() as single
    return this.x
end function

function __spell.getY() as single
    return this.y
end function



#include once "allegro.bi"

type __wgeSprite
    
    private:
    
        texture as BITMAP ptr
       
    public:
    
        declare constructor(byval as string)
        declare destructor()
        'xy
        declare sub render overload(byval as bitmap ptr,byval as single,byval as single)
        'xywh
        declare sub render overload(byval as bitmap ptr,byval as single,byval as single,byval as single,byval as single)
        'xyr
        declare sub render overload(byval as bitmap ptr,byval as single,byval as single,byval as single)
        'xyrs
        declare sub renderEx(byval as bitmap ptr,byval as single,byval as single,byval as single,byval as single)

        declare function getWidth() as integer
        declare function getHeight() as integer

end type

constructor __wgeSprite(byval path as string)

    this.texture=load_bitmap(path,0)

end constructor

destructor __wgeSprite()

    destroy_bitmap(this.texture)

end destructor

sub __wgeSprite.render overload(byval buffer as bitmap ptr,byval x as single,byval y as single)

    draw_sprite(buffer,this.texture,x-this.texture->w/2,y-this.texture->h/2)

end sub

sub __wgeSprite.render overload(byval buffer as bitmap ptr,byval x as single,byval y as single,byval w as single,byval h as single)

    stretch_sprite(buffer,this.texture,x-w/2,y-h/2,w,h)

end sub

sub __wgeSprite.render overload(byval buffer as bitmap ptr,byval x as single,byval y as single,byval r as single)
    
    pivot_sprite(buffer,this.texture,x,y,this.texture->w/2,this.texture->h/2,itofix(r))
    
end sub

sub __wgeSprite.renderEx(byval buffer as bitmap ptr,byval x as single,byval y as single,byval r as single,byval s as single)
    
    pivot_scaled_sprite(buffer,this.texture,x,y,this.texture->w/2,this.texture->h/2,itofix(r),ftofix(s))
    
end sub

function __wgeSprite.getWidth() as integer
    return this.texture->w
end function

function __wgeSprite.getHeight() as integer
    return this.texture->h
end function




#ifndef PI
#define PI 3.1415926535897932384626433832795
#endif

#include once "allegro.bi"
        

'allegro_message(msg)
        
        
type __wgeSystem


    private:
        screenWidth as integer
        screenHeight as integer
        screenDepth as integer
        
        showMouse as ubyte
        mouseX as integer
        mouseY as integer
        
        textHeight as integer
        
        'timer
        dt as double
        lastTime as double
        
        'state
        state as string
        
    public:

        declare constructor(byval as integer=640,byval as integer=480,byval as integer=32,byval as ubyte=0)
        declare destructor
        declare sub beginStep()
        declare sub endStep()
        
        declare function getDelta() as single
        
        declare function getScreenWidth() as integer
        declare function getScreenHeight() as integer
        declare function getScreenDepth() as integer
        declare function getTextHeight() as integer
       
        declare function distance(byval as single,byval as single,byval as single,byval as single) as single
        declare function clampValue overload(byval as integer,byval as integer,byval as integer) as integer
        declare function clampValue overload(byval as single,byval as single,byval as single) as single
        declare function wrapValue overload(byval as integer,byval as integer,byval as integer) as integer
        declare function wrapValue overload(byval as single,byval as single,byval as single) as single        
        declare function polarity overload(byval as integer) as integer
        declare function polarity overload(byval as single) as single
        declare function getAngle(byval as single,byval as single,byval as single,byval as single) as single
        declare function newX(byval as single,byval as single,byval as single) as single
        declare function newY(byval as single,byval as single,byval as single) as single
        declare function rand(byval as single,byval as single) as single
        declare function randInt(byval as integer,byval as integer) as integer
        declare function degToFixed(byval as single) as single
        declare function fixedToDeg(byval as single) as single
        declare function circleCollision(byval as single,byval as single,byval as single,byval as single,byval as single,byval as single) as ubyte

        declare function getState() as string
        declare sub setState(byval as string)

        'draw graphics to this...
        buffer as bitmap ptr
end type

constructor __wgeSystem(byval w as integer,byval h as integer,byval d as integer,byval showMouse as ubyte)

    allegro_init()
    install_keyboard()
    install_timer()
    install_mouse()
    
    set_color_depth(d)
    set_gfx_mode(GFX_AUTODETECT_WINDOWED,w,h,0,0)
    
    this.screenWidth=w
    this.screenHeight=h
    this.screenDepth=d
    
    this.textHeight=text_height(font)
    
    this.showMouse=showMouse
    
    this.buffer=create_bitmap(w,h)
    
    this.lastTime=timer()
    this.dt=timer()-this.lastTime
    
    randomize timer()
    
end constructor

destructor __wgeSystem()

    allegro_exit()

end destructor

sub __wgeSystem.beginStep()
    
    scare_mouse()
    clear_to_color(this.buffer,makecol(100,100,100))
    
    this.dt=timer()-this.lastTime
    this.lastTime=timer()

end sub

sub __wgeSystem.endStep()
    
    if this.showMouse<>0 then show_mouse(this.buffer)
    blit(this.buffer,screen,0,0,0,0,this.screenWidth,this.screenHeight)
    
end sub

function __wgeSystem.getDelta() as single
    
    return this.dt
    
end function

function __wgeSystem.getScreenWidth() as integer
    
    return this.screenWidth
    
end function

function __wgeSystem.getScreenHeight() as integer
    
    return this.screenHeight
    
end function

function __wgeSystem.getScreenDepth() as integer
    
    return this.screenDepth
    
end function

function __wgeSystem.getTextHeight() as integer
    
    return this.textHeight
    
end function

function __wgeSystem.distance(byval x1 as single,byval y1 as single,byval x2 as single,byval y2 as single) as single
    return sqr((x2-x1)^2 + (y2-y1)^2)
end function

function __wgeSystem.clampValue overload(byval a as integer,byval b as integer,byval c as integer) as integer
    dim as integer mn=min(b,c)
    dim as integer mx=max(b,c)
    if a<mn then a=mn
    if a>mx then a=mx
    return a
end function

function __wgeSystem.clampValue overload(byval a as single,byval b as single,byval c as single) as single
    dim as single mn=min(b,c)
    dim as single mx=max(b,c)
    if a<mn then a=mn
    if a>mx then a=mx
    return a
end function

function __wgeSystem.wrapValue overload(byval a as integer,byval mn as integer,byval mx as integer) as integer
    If a<mn then
		a=mx-Abs(mn-a)
	Elseif a>mx then
        a=mn+Abs(mx-a)
	EndIf
	if a<mn or a>mx Then a=this.wrapValue(a,mn,mx)
    return a
end function

function __wgeSystem.wrapValue overload(byval a as single,byval mn as single,byval mx as single) as single   
    If a<mn then
		a=mx-Abs(mn-a)
	Elseif a>mx then
        a=mn+Abs(mx-a)
	EndIf
	if a<mn or a>mx Then a=this.wrapValue(a,mn,mx)
    return a
end function

function __wgeSystem.polarity overload(byval a as integer) as integer
    if a=0 then
        return 0
    elseif a>0 then
        return 1
    elseif a<0 then
        return -1
    endif
end function

function __wgeSystem.polarity overload(byval a as single) as single
    if a=0 then
        return 0
    elseif a>0 then
        return 1
    elseif a<0 then
        return -1
    endif    
end function


function __wgeSystem.getAngle(byval x1 as single,byval y1 as single,byval x2 as single,byval y2 as single) as single
    dim faceRadians as single
    dim faceDegrees as single
    faceRadians=atan2(y2-y1,x2-x1)
    faceDegrees=faceRadians*180/PI
    return faceDegrees+90
end function

function __wgeSystem.rand(byval mn as single,byval mx as single) as single
    return rnd*(mx-mn)+mn
end function

function __wgeSystem.randInt(byval mn as integer,byval mx as integer) as integer
    return int(rnd*(mx-mn)+mn)
end function

function __wgeSystem.newX(byval x as single,byval angle as single,byval amount as single) as single
    x-=sin(angle*(PI/180))*amount*-1
    return x
end function

function __wgeSystem.newY(byval y as single,byval angle as single,byval amount as single) as single
    y-=cos(angle*(PI/180))*amount
    return y
end function

function __wgeSystem.degToFixed(byval n as single) as single
    return n*0.7111
end function

function __wgeSystem.fixedToDeg(byval n as single) as single
    return n/0.7111
end function

function __wgeSystem.circleCollision(byval x1 as single,byval y1 as single,byval r1 as single,byval x2 as single,byval y2 as single,byval r2 as single) as ubyte
    if this.distance(x1,y1,x2,y2)<r1+r2 then
        return 1
    else
        return 0
    endif
end function

function __wgeSystem.getState() as string
    return this.state
end function

sub __wgeSystem.setState(byval state as string)
    this.state=state
end sub


#include once"allegro.bi"

type __world
    
    private:
        texture as bitmap ptr
        map(1 to 20,1 to 15) as ubyte
    
    public:
        declare constructor(byval as __wgeSystem ptr,byval as string)
        declare destructor()
        declare sub render(byval as __wgeSystem ptr)
        declare function checkMap(byval as integer,byval as integer)as ubyte
    
end type

constructor __world(byval game as __wgeSystem ptr,byval path as string)

    this.texture=load_bitmap(path,0)
    
    'build map
    dim i as integer
    dim j as integer
    
    for j=1 to game->buffer->h/32
        for i=1 to game->buffer->w/32
            
            if ((i>=4 and i<=7) or (i>=14 and i<=17)) and ((j>=4 and j<=6) or (j>=10 and j<=12)) then this.map(i,j)=1
            if (i>4 and i<17 and j>4 and j<12) then this.map(i,j)=0
            if i=1 or i=20 or j=1 or j=15 then this.map(i,j)=1
            
            if this.map(i,j)=0 then
                'with a chance, add water (roughly 8 pieces)
                if game->randInt(0,20*15/8)=0 then
                    this.map(i,j)=2
                endif
                'with a chance, add lava (roughly 8 pieces)
                if game->randInt(0,20*15/8)=0 then
                    this.map(i,j)=3
                endif
            endif
            
        next i
    next j

end constructor

destructor __world()

    destroy_bitmap(this.texture)

end destructor

sub __world.render(byval game as __wgeSystem ptr)
    
    dim i as integer
    dim j as integer
    
    for j=1 to game->buffer->h/32
        for i=1 to game->buffer->w/32
            select case this.map(i,j)
            case 0:blit(this.texture,game->buffer,0,0,(i-1)*32,(j-1)*32,32,32)
            case 1:blit(this.texture,game->buffer,32,0,(i-1)*32,(j-1)*32,32,32)
            case 2:blit(this.texture,game->buffer,64,0,(i-1)*32,(j-1)*32,32,32)
            case 3:blit(this.texture,game->buffer,96,0,(i-1)*32,(j-1)*32,32,32)
            end select
        next i
    next j
    
end sub

rem add 1 if doing int(x/32) because this is 1-20,1-15, NOT 0-19,0-14
function __world.checkMap(byval x as integer,byval y as integer)as ubyte
    return this.map(x,y)
end function







